/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import com.jnetx.javax.sip.util.Parametrized;

import javax.sip.InvalidArgumentException;
import javax.sip.header.ReasonHeader;
import java.text.ParseException;

/**
 * This interface represents the Reason header, as defined by
 * <a href = "http://www.ietf.org/rfc/rfc3326.txt">RFC3326</a>, this header is
 * not part of RFC3261.
 * <p/>
 * The ReasonHeader provides information on why a SIP request was issued, often
 * useful when creating services and also used to encapsulate a final status code in
 * a provisional response, which is needed to resolve the "Heterogeneous Error
 * Response Forking Problem".
 * <p/>
 * The Reason header field appears to be most useful for BYE and CANCEL requests,
 * but it can appear in any request within a dialog, in any CANCEL request and
 * in 155 (Update Requested) responses. When used in requests, clients and
 * servers are free to ignore this header field. It has no impact on protocol
 * processing.
 * <p/>
 * Examples of the ReasonHeader usage are:
 * <ul>
 * <li> A SIP CANCEL request can be issued if the call has completed on another
 * branch or was abandoned before answer. While the protocol and system behavior
 * is the same in both cases, namely, alerting will cease, the user interface
 * may well differ. In the second case, the call may be logged as a missed call,
 * while this would not be appropriate if the call was picked up elsewhere.
 * <li> Third party call controllers sometimes generate a SIP request upon
 * reception of a SIP response from another dialog. Gateways generate SIP
 * requests after receiving messages from a different protocol than SIP. In
 * both cases the client may be interested in knowing what triggered the SIP
 * request.
 * <li> An INVITE can sometimes be rejected not because the session initiation
 * was declined, but because some aspect of the request was not acceptable. If
 * the INVITE forked and resulted in a rejection, the error response may never
 * be forwarded to the client unless all the other branches also reject the
 * request. This problem is known as the "Heterogeneous Error Response Forking
 * Problem". The header field defined in this draft allows encapsulating the
 * final error response in a 155 (Update Requested) provisional response.
 * </ul>
 * A server must ignore Headers that it does not understand. A proxy must not
 * remove or modify Headers that it does not understand.
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class ReasonHeaderImpl extends ParametrizedHeaderBase implements ReasonHeader {
    private final static ReasonHeaderParser parser = new ReasonHeaderParser();

    private String protocol;

    public ReasonHeaderImpl() {
        super(ReasonHeader.NAME);
    }

    ReasonHeaderImpl(byte[] data, int start, int end) {
        super(ReasonHeader.NAME, data, start, end);
    }

    public Object clone() {
        final ReasonHeaderImpl header = new ReasonHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.cloneParameters(this);
            header.protocol = this.protocol;
        }
        return header;
    }

    protected HeaderParser getParser() {
        return parser;
    }

    protected String getValueAsString() {
        return protocol;
    }

    /**
     * Gets the cause value of the ReasonHeader
     *
     * @return the integer value of the cause of the ReasonHeader
     */
    public int getCause() {
        final String causeStr = getParameter("cause");
        int cause = 0;
        if (causeStr != null) {
            try {
                cause = Integer.parseInt(causeStr);
            } catch (Exception ex) {
            }
        }
        return cause;
    }

    /**
     * Sets the cause value of the ReasonHeader. Any SIP status code MAY
     * appear in the Reason header field of a request, assuming the protocol
     * field of the ReasonHeader is SIP.
     *
     * @param cause the new integer value of the cause of the ReasonHeader
     * @throws javax.sip.InvalidArgumentException
     *          if the cause value is less than zero.
     */
    public void setCause(int cause) throws InvalidArgumentException {
        try {
            setParameter("cause", Integer.toString(cause), Parametrized.QuotationType.NONE);
        } catch (ParseException e) {
            throw new InvalidArgumentException("Cannot set a parameter 'cause'!", e);
        }
    }

    /**
     * Sets the protocol of the ReasonHeader, for example SIP or Q.850.
     *
     * @param protocol the new string value of the protocol of the ReasonHeader
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the protocol value.
     */
    public void setProtocol(String protocol) throws ParseException {
        parse();
        this.protocol = protocol;
        invalidateHeaderData();
    }

    /**
     * Gets the protocol value of the ReasonHeader
     *
     * @return the string value of the protocol of the ReasonHeader
     */
    public String getProtocol() {
        parse();
        return this.protocol;
    }

    /**
     * Sets the text value of the ReasonHeader.
     *
     * @param text the new string value of the text of the ReasonHeader
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the text value.
     */
    public void setText(String text) throws ParseException {
        setParameter("text", text, Parametrized.QuotationType.DOUBLE);
    }

    /**
     * Gets the text value of the ReasonHeader
     *
     * @return the string value of the text of the ReasonHeader
     */
    public String getText() {
        return getParameter("text");
    }
}
/*
 * $Log$
 */